package com.zmn.oms.admin.controller.sync;

import com.alibaba.nacos.shaded.com.google.common.collect.ImmutableMap;
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
import com.google.common.collect.Lists;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.admin.controller.OmsBaseController;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderPayConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.datasync.ElasticSearchDataSyncService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.work.orderpay.ZsOrderPayBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.pay.gateway.common.model.dro.PayGatewayDRO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 类描述：订单支付记录同步
 * @author heciqi
 * @date 2021/8/18 15:58
 */
@Slf4j
@RequestMapping("/test/sync")
@RestController
public class SyncOrderPayController extends OmsBaseController {
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private ElasticSearchDataSyncService elasticSearchDataSyncService;
    @Autowired
    private ZsOrderPayBService zsOrderPayBService;


    /**
     * 手动调用渠道支付接口
     * /test/sync/invokepaychannelamount?workIds=xxx
     * @param workIds
     * @return
     */
    @GetMapping(value = "/invokepaychannelamount")
    public ResultDTO invokePayChannelAmount(String workIds) {
        log.info("SyncOrderPayController#invokePayChannelAmount：{}", workIds);
        if (StringUtil.isBlank(workIds)) {
            return ResultDTO.fail("参数有误");
        }

        List<String> errMsgList = Lists.newArrayList();
        String[] arrWorkId = workIds.split(",");
        List<Long> workIdList = Arrays.stream(arrWorkId).map(Long::parseLong).collect(Collectors.toList());
        List<OrderWork> orderWorks = orderWorkService.listOrderWorkByOrderIdList(workIdList);
        Map<Long, OrderWork> orderWorkMap = Maps.uniqueIndex(orderWorks, OrderWork::getWorkId);
        for (Long workId : workIdList) {
            OrderWork orderWork = orderWorkMap.get(workId);
            try {
                PayGatewayDRO payGatewayDRO = zsOrderPayBService.payChannelPrepaidAmount(orderWork);
            } catch (Exception e) {
                errMsgList.add(workId + "==>" + e.getMessage());
                log.error("调用接口失败" +e.getMessage(),e);
            }
        }
        if (CollectionUtil.isNullOrEmpty(errMsgList)) {
            return ResultDTO.success("手动调用渠道支付成功");
        } else {
            return ResultDTO.success("手动调用渠道失败订单==>" + errMsgList);
        }
    }

    /**
     * 同步退款订单支付
     * @param workIds
     * @return
     */
    @GetMapping(value = "/syncrefundorderpay")
    public ResultDTO syncRefundOrderPay(String workIds) {
        log.info("SyncOrderPayController#syncrefundorderpay：{}", workIds);
        if (StringUtil.isBlank(workIds)) {
            return ResultDTO.fail("参数有误");
        }
        String[] arrWorkId = workIds.split(",");
        List<Long> workList = Lists.newArrayList();
        for (String s : arrWorkId) {
            workList.add(Long.parseLong(s));
        }
        log.info("退款单订单同步==>{}", workIds);
        List<OrderWork> orderWorks = orderWorkService.listEsOrderWorkByOrderIdList(workList);
        for (OrderWork orderWork : orderWorks) {
            if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
                continue;
            }
            OrderPay orderPay = new OrderPay();
            orderPay.setOrderId(orderWork.getOrderId());
            orderPay.setWorkId(orderWork.getWorkId());
            orderPay.setTradeType(PayConsts.PAY_TRADE_TYPE_REFUND);
            orderPay.setRefundType(2);
            orderPay.setPayStatus(PayConsts.REFUND_STATUS_DONE);
            orderPay.setPayChannelId(PayConsts.PAY_CHANNEL_PLATFORM_OFFLINE);
            orderPay.setPayType(PayConsts.PAY_TYPE_MANUAL);
            orderPay.setPayTargetChannelId(PayConsts.PAY_CHANNEL_PLATFORM_CASH);
            orderPay.setPayTargetType(0);
            orderPay.setMergeInnerTradeNo("");
            orderPay.setMergePayOutTradeNo("");
            orderPay.setMergeAmount(0);
            orderPay.setInnerTradeNo("");
            orderPay.setPayOutTradeNo("");
            orderPay.setPayTime(orderWork.getRefundTime());
            orderPay.setImageUrls("");
            orderPay.setPayerType(0);
            orderPay.setPayerId(0L);
            orderPay.setPayerAccountId(0L);
            orderPay.setPayerThirdAccount("");
            orderPay.setPayerThirdAccountName("");
            orderPay.setPayerThirdAccountBank("");
            orderPay.setPayeeType(0);
            orderPay.setPayeeId(0L);
            orderPay.setPayeeAccountId(0L);
            orderPay.setPayeeThirdAccount("");
            orderPay.setPayeeThirdAccountName("");
            orderPay.setPayeeThirdAccountBank("");
            orderPay.setRefundImageData("");
            orderPay.setAmount(orderWork.getRefundAmount());
            orderPay.setLongitude(0.0D);
            orderPay.setLatitude(0.0D);
            orderPay.setCreater("ivan");
            orderPay.setUpdater("ivan");
            orderPay.setCreateTime(new Date());
            orderPay.setUpdateTime(new Date());
            orderPayService.insertOrderPay(orderPay);
        }
        return ResultDTO.success("退款单订单支付同步成功");
    }

    /**
     * 同步退款订单支付
     * @param workIds
     * @return
     */
    @GetMapping(value = "/synchannelorderpay")
    public ResultDTO syncChannelPrepayOrderPay(String workIds) {
        log.info("SyncOrderPayController#syncrefundorderpay：{}", workIds);
        if (StringUtil.isBlank(workIds)) {
            return ResultDTO.fail("参数有误");
        }
        String[] arrWorkId = workIds.split(",");
        List<Long> workList = Lists.newArrayList();
        for (String s : arrWorkId) {
            workList.add(Long.parseLong(s));
        }
        log.info("渠道支付订单同步==>{}", workIds);
        List<OrderWork> orderWorks = orderWorkService.listEsOrderWorkByOrderIdList(workList);
        for (OrderWork orderWork : orderWorks) {
            if (NumberUtil.isNullOrZero(orderWork.getChannelPrepayAmount())) {
                continue;
            }
            OrderPay orderPay = new OrderPay();
            orderPay.setOrderId(orderWork.getOrderId());
            orderPay.setWorkId(orderWork.getWorkId());
            orderPay.setAmountType(OrderPayConsts.ORDER_PAY_CHANNEL_PREPAY);
            orderPay.setPayPlat(orderWork.getPlatWork());
            orderPay.setTradeType(PayConsts.PAY_TRADE_TYPE_INTIME);
            orderPay.setPayStatus(PayConsts.PAY_STATUS_DONE);
            orderPay.setPayChannelId(PayConsts.PAY_CHANNEL_PLATFORM_CHANNEL);
            orderPay.setPayType(PayConsts.PAY_TYPE_INTO);
            orderPay.setMergeInnerTradeNo("");
            orderPay.setMergePayOutTradeNo("");
            orderPay.setMergeAmount(0);
            orderPay.setInnerTradeNo("");
            orderPay.setPayOutTradeNo("");
            orderPay.setPayTime(orderWork.getCompleteTime());
            orderPay.setImageUrls("");
            orderPay.setPayerType(0);
            orderPay.setPayerId(0L);
            orderPay.setPayerAccountId(0L);
            orderPay.setPayerThirdAccount("");
            orderPay.setPayerThirdAccountName("");
            orderPay.setPayerThirdAccountBank("");
            orderPay.setPayeeType(0);
            orderPay.setPayeeId(0L);
            orderPay.setPayeeAccountId(0L);
            orderPay.setPayeeThirdAccount("");
            orderPay.setPayeeThirdAccountName("");
            orderPay.setPayeeThirdAccountBank("");
            orderPay.setRefundImageData("");
            orderPay.setAmount(orderWork.getChannelPrepayAmount());
            orderPay.setLongitude(0.0D);
            orderPay.setLatitude(0.0D);
            orderPay.setCreater("ivan");
            orderPay.setUpdater("ivan");
            orderPay.setCreateTime(new Date());
            orderPay.setUpdateTime(new Date());
            orderPayService.insertOrderPay(orderPay);
        }
        return ResultDTO.success("订单预付支付同步成功");
    }


    /**
     * 同步支付信息
     * @param workIds
     * @return
     */
    @GetMapping(value = "/syncorderpay")
    public ResultDTO syncOrderPay(String workIds) {
        log.info("SyncOrderPayController#syncOrderPay：{}", workIds);
        if (StringUtil.isBlank(workIds)) {
            return ResultDTO.fail("参数有误");
        }
        String[] arrWorkId = workIds.split(",");
        List<Long> workList = Lists.newArrayList();
        for (String s : arrWorkId) {
            workList.add(Long.parseLong(s));
        }
        log.info("订单支付同步==>{}", workIds);
        List<OrderWork> orderWorks = orderWorkService.listEsOrderWorkByOrderIdList(workList);
        for (OrderWork orderWork : orderWorks) {
            if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND) && NumberUtil.isNotNullOrZero(orderWork.getRefundAmount())) {
                log.info("{}同步退款单", orderWork.getWorkId());
                this.insertOrderPay(orderWork.getOrderId(), orderWork.getWorkId(), orderWork.getPlatWork(), 0,
                        PayConsts.PAY_TRADE_TYPE_REFUND, PayConsts.REFUND_STATUS_DONE, PayConsts.PAY_CHANNEL_PLATFORM_OFFLINE,
                        PayConsts.PAY_TYPE_MANUAL, orderWork.getRefundTime(), orderWork.getRefundAmount());
                continue;

            }
            boolean paidChannelPrepayAmount = NumberUtil.isNotNullOrZero(orderWork.getChannelPrepayAmount());
            if (paidChannelPrepayAmount) {
                log.info("{}同步渠道收款", orderWork.getWorkId());
                this.insertOrderPay(orderWork.getOrderId(), orderWork.getWorkId(), orderWork.getPlatWork(), OrderPayConsts.ORDER_PAY_CHANNEL_PREPAY,
                        PayConsts.PAY_TRADE_TYPE_INTIME, PayConsts.PAY_STATUS_DONE, PayConsts.PAY_CHANNEL_PLATFORM_CHANNEL,
                        PayConsts.PAY_TYPE_INTO, orderWork.getCompleteTime(), orderWork.getChannelPrepayAmount());
            }
            boolean paidPrepayAmount = NumberUtil.isNotNullOrZero(orderWork.getPrepayAmount()) && Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE);
            if (paidPrepayAmount) {
                log.info("{}同步平台收款", orderWork.getWorkId());
                this.insertOrderPay(orderWork.getOrderId(), orderWork.getWorkId(), orderWork.getPlatWork(), OrderPayConsts.ORDER_PAY_PREPAY,
                        PayConsts.PAY_TRADE_TYPE_INTIME, orderWork.getPrepayStatus(), orderWork.getPrepayChannelId(),
                        0, orderWork.getPrepayTime(), orderWork.getPrepayAmount());
            }

            boolean paidDepositAmount = NumberUtil.isNotNullOrZero(orderWork.getDepositAmount()) && Objects.equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE);
            if (paidDepositAmount) {
                log.info("{}同步定金收款", orderWork.getWorkId());
                this.insertOrderPay(orderWork.getOrderId(), orderWork.getWorkId(), orderWork.getPlatWork(), OrderPayConsts.ORDER_PAY_DEPOSIT,
                        PayConsts.PAY_TRADE_TYPE_INTIME, orderWork.getDepositStatus(), orderWork.getDepositChannelId(),
                        0, orderWork.getDepositTime(), orderWork.getDepositAmount());
            }

            boolean paidMasterAmount = NumberUtil.isNotNullOrZero(orderWork.getMasterAmount()) && Objects.equals(orderWork.getMasterPayStatus(), PayConsts.PAY_STATUS_DONE);
            if (paidMasterAmount) {
                log.info("{}同步工程师收款", orderWork.getWorkId());
                this.insertOrderPay(orderWork.getOrderId(), orderWork.getWorkId(), orderWork.getPlatWork(), OrderPayConsts.ORDER_PAY_MASTER,
                        PayConsts.PAY_TRADE_TYPE_INTIME, orderWork.getMasterPayStatus(), orderWork.getMasterPayChannelId(),
                        0, orderWork.getMasterPayTime(), orderWork.getMasterAmount());
            }

            boolean paidDiscountAmount = NumberUtil.isNotNullOrZero(orderWork.getDiscountAmount());
            if (paidDiscountAmount) {
                log.info("{}同步优惠", orderWork.getWorkId());
                this.insertOrderPay(orderWork.getOrderId(), orderWork.getWorkId(), orderWork.getPlatWork(), 0,
                        PayConsts.PAY_TRADE_TYPE_INTIME, PayConsts.PAY_STATUS_DONE, PayConsts.PAY_CHANNEL_PLATFORM_DISCOUNT,
                        PayConsts.PAY_TYPE_INTO, orderWork.getCompleteTime(), orderWork.getDiscountAmount());
            }

        }
        return ResultDTO.success("订单支付同步成功");
    }

    private void insertOrderPay(Long orderId, Long workId, Integer platWork, Integer amountType, Integer tradeType, Integer payStatus, Integer payChannelId, Integer payType, Date payTime, Integer payAmount) {
        if (Objects.equals(payChannelId, PayConsts.PAY_CHANNEL_PLATFORM_DISCOUNT)) {
            List<OrderPay> orderPayList = orderPayService.listOrderPayByOrderIdAndWorkId(orderId, workId);
            // 优惠支付记录
            if (orderPayList.stream().anyMatch(e -> Objects.equals(e.getPayChannelId(), payChannelId))) {
                int sum = orderPayList.stream().filter(e -> Objects.equals(e.getPayChannelId(), payChannelId)).mapToInt(e -> e.getAmount()).sum();
                if (sum == payAmount) {
                    log.info("{}已存在优惠支付记录，不处理", orderId);
                    return;
                }
                List<OrderPay> collect = orderPayList.stream().filter(e -> Objects.equals(e.getPayChannelId(), payChannelId)).collect(Collectors.toList());
                for (OrderPay orderPay : collect) {
                    OrderPay upOrderPay = new OrderPay();
                    upOrderPay.setOrderPayId(orderPay.getOrderPayId());
                    upOrderPay.setOrderId(orderPay.getOrderId());
                    log.info("{}删除已有支付记录", orderId);
                    orderPayService.deleteByKey(upOrderPay);
                }
            }
        }

        if (NumberUtil.isNotNullOrZero(amountType) && NumberUtil.isNotNullOrZero(tradeType)) {
            int count = orderPayService.countByWorkIdAndAmountType(orderId, workId, amountType, tradeType);
            if (count > 0) {
                log.info("{}已存在{}支付记录，不处理", orderId, OrderPayConsts.getAmountTypeName(amountType));
                return;
            }
        }
        OrderPay orderPay = new OrderPay();
        orderPay.setOrderId(orderId);
        orderPay.setWorkId(workId);
        orderPay.setPayPlat(platWork);
        orderPay.setAmountType(amountType);
        orderPay.setTradeType(tradeType);
        if (Objects.equals(tradeType, PayConsts.PAY_TRADE_TYPE_REFUND)) {
            orderPay.setRefundType(2);
            orderPay.setPayTargetChannelId(PayConsts.PAY_CHANNEL_PLATFORM_CASH);
        }
        orderPay.setPayStatus(payStatus);
        orderPay.setPayChannelId(payChannelId);
        orderPay.setPayType(payType);
        orderPay.setMergeInnerTradeNo("");
        orderPay.setMergePayOutTradeNo("");
        orderPay.setMergeAmount(0);
        orderPay.setInnerTradeNo("");
        orderPay.setPayOutTradeNo("");
        orderPay.setPayTime(payTime);
        orderPay.setImageUrls("");
        orderPay.setPayerType(0);
        orderPay.setPayerId(0L);
        orderPay.setPayerAccountId(0L);
        orderPay.setPayerThirdAccount("");
        orderPay.setPayerThirdAccountName("");
        orderPay.setPayerThirdAccountBank("");
        orderPay.setPayeeType(0);
        orderPay.setPayeeId(0L);
        orderPay.setPayeeAccountId(0L);
        orderPay.setPayeeThirdAccount("");
        orderPay.setPayeeThirdAccountName("");
        orderPay.setPayeeThirdAccountBank("");
        orderPay.setRefundImageData("");
        orderPay.setAmount(payAmount);
        orderPay.setLongitude(0.0D);
        orderPay.setLatitude(0.0D);
        orderPay.setCreater("ivan");
        orderPay.setUpdater("ivan");
        orderPay.setCreateTime(new Date());
        orderPay.setUpdateTime(new Date());
        log.info("插入支付人记录{}", orderPay);
        orderPayService.insertOrderPay(orderPay);
        // 同步支付明细
        elasticSearchDataSyncService.syncPayIndex(orderId);
    }

}
